﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;

namespace Utility
{
    /// <summary>
    /// Conversion Classes, Convert something to something
    /// </summary>
    public class Conversion
    {

    }
    /// <summary>
    /// Image modification and creation functions
    /// </summary>
    public class Image
    {
        /// <summary>
        /// Saves a Texture2D to disk.
        /// </summary>
        /// <param name="texture">The Texture to be saved.</param>
        /// <param name="name">The name of the texture to be saved. Can save as any image type.</param>
        /// <returns>Nothing.</returns>
        public static void SaveTexture2DToImage(Texture2D texture, string name)
        {
            string[] temp = name.Split('.');
            byte[] tb = texture.EncodeToPNG();
            File.Open(name, FileMode.Create).Write(tb, 0, tb.Length);
        }

        /// <summary>
        /// Uses alpha channel to combine textures together
        /// </summary>
        /// <param name="InputTextures">Textures to combine, Index 0 is used for size</param>
        /// <param name="AlphaCombind">Should the texture combine use the alpha of the pixels</param>
        /// <returns></returns>
        public static Texture2D CombineTextures2D(Texture2D[] InputTextures)
        {
            //Using the base texture for size and asuming there all the same size textures,
            //will add in checks for size next
            Texture2D Output = InputTextures[0];
            for (int Index = 1; Index < InputTextures.Length; Index++)
            {
                //make all the pixels a equal their alpha channel in magintude
                Output = CombineTexture2D(Output, InputTextures[Index]);
            }
            return Output;
        }
        
        /// <summary>
        /// Splats two texture2D's using the Color.Lerp option on each Pixel
        /// </summary>
        /// <param name="Primary">Base Texture</param>
        /// <param name="Overlap">Texture to Lerp to based on its alpha</param>
        /// <returns>The combined texture</returns>
        public static Texture2D CombineTexture2D(Texture2D Primary, Texture2D Overlap)
        {
            Texture2D Output = new Texture2D(Primary.width, Primary.height);
            for (int y = 0; y < Primary.height; y++)
            {
                for (int x = 0; x < Primary.width; x++)
                {
                    Color Prim = Primary.GetPixel(x, y);
                    Color Over = Overlap.GetPixel(x, y);
                    Color New = Color.Lerp(Prim, Over, Over.a);
                    Output.SetPixel(x, y, New);
                }
            }
            return Output;
        }


    }
    /// <summary>
    /// Info Classes, Anything that you would want to run to find something out in the world
    /// </summary>
    public class Info
    {
        /// <summary>
        /// Raycast and return the distance.
        /// </summary>
        /// <param name="Position">Start Location of the trace</param>
        /// <param name="Direction">Direction the trace should go in</param>
        /// <param name="MaxDistance">The max length you would like the trace to go to, Passing in 0 is Unlimited</param>
        /// <returns>Returns the distance to hit, if nothing was hit then it returns maxdistance, If you passed in 0 it returns hit distance or 0</returns>
        public static float Trace(Vector3 Position, Vector3 Direction, float MaxDistance)
        {
            Ray TraceRay = new Ray(Position, Direction);
            RaycastHit TraceHit;
            if (MaxDistance != 0)
            {
                if (Physics.Raycast(TraceRay, out TraceHit, MaxDistance))
                {
                    return TraceHit.distance;
                }
                else
                {
                    return MaxDistance;
                }
            }
            else
            {
                if (Physics.Raycast(TraceRay, out TraceHit))
                {
                    return TraceHit.distance;
                }
                else
                {
                    return 0;
                }
            }
        }
        /// <summary>
        /// Raycast and return the distance.
        /// </summary>
        /// <param name="Position">Start Location of the trace</param>
        /// <param name="Direction">Direction the trace should go in</param>
        /// <param name="MaxDistance">The max length you would like the trace to go to, Passing in 0 is Unlimited</param>
        /// <param name="DrawRay">Should Unity draw a debug line showing the raycast? Distance Checks are White</param>
        /// <returns>Returns the distance to hit, if nothing was hit then it returns maxdistance, If you passed in 0 it returns hit distance or 0</returns>
        public static float Trace(Vector3 Position, Vector3 Direction, float MaxDistance, bool DrawRay)
        {
            Ray TraceRay = new Ray(Position, Direction);
            RaycastHit TraceHit;
            if (MaxDistance != 0)
            {
                if (Physics.Raycast(TraceRay, out TraceHit, MaxDistance))
                {
                    if (DrawRay)
                    {
                        Debug.DrawLine(TraceRay.origin, TraceHit.point, Color.white, 2);
                    }
                    return TraceHit.distance;
                }
                else
                {
                    if (DrawRay)
                    {
                        Debug.DrawLine(TraceRay.origin, TraceRay.GetPoint(MaxDistance), Color.white, 2);
                    }
                    return MaxDistance;
                }
            }
            else
            {
                if (Physics.Raycast(TraceRay, out TraceHit))
                {
                    if (DrawRay)
                    {
                        Debug.DrawLine(TraceRay.origin, TraceHit.point, Color.white, 2);
                    }
                    return TraceHit.distance;
                }
                else
                {
                    if (DrawRay)
                    {
                        Debug.DrawLine(TraceRay.origin, TraceRay.GetPoint(100), Color.white, 2);
                    }
                    return 0;
                }
            }
        }
        /// <summary>
        /// Raycast and return the RaycastHit.
        /// </summary>
        /// <param name="Position">Start Location of the trace</param>
        /// <param name="Direction">Direction the trace should go in</param>
        /// <param name="MaxDistance">The max length you would like the trace to go to, Passing in 0 is Unlimited</param>
        /// <returns>Returns the RaycastHit, if nothing was hit then it returns a Blank RaycastHit</returns>
        public static RaycastHit TraceInfo(Vector3 Position, Vector3 Direction, float MaxDistance)
        {
            Ray TraceRay = new Ray(Position, Direction);
            RaycastHit TraceHit;
            if (MaxDistance != 0)
            {
                if (Physics.Raycast(TraceRay, out TraceHit, MaxDistance))
                {
                    return TraceHit;
                }
                else
                {
                    return TraceHit;
                }
            }
            else
            {
                if (Physics.Raycast(TraceRay, out TraceHit))
                {
                    return TraceHit;
                }
                else
                {
                    return TraceHit;
                }
            }
        }
        /// <summary>
        /// Raycast and return the RaycastHit.
        /// </summary>
        /// <param name="Position">Start Location of the trace</param>
        /// <param name="Direction">Direction the trace should go in</param>
        /// <param name="MaxDistance">The max length you would like the trace to go to, Passing in 0 is Unlimited</param>
        /// <param name="DrawRay">Should Unity draw a debug line showing the raycast? RaycastHit Checks are Green</param>
        /// <returns>Returns the RaycastHit, if nothing was hit then it returns a Blank RaycastHit</returns>
        public static RaycastHit TraceInfo(Vector3 Position, Vector3 Direction, float MaxDistance, bool DrawRay)
        {
            Ray TraceRay = new Ray(Position, Direction);
            RaycastHit TraceHit;
            if (MaxDistance != 0)
            {
                if (Physics.Raycast(TraceRay, out TraceHit, MaxDistance))
                {
                    if (DrawRay)
                    {
                        Debug.DrawLine(TraceRay.origin, TraceHit.point, Color.green, 2);
                    }
                    return TraceHit;
                }
                else
                {
                    if (DrawRay)
                    {
                        Debug.DrawLine(TraceRay.origin, TraceRay.GetPoint(MaxDistance), Color.green, 2);
                    }
                    return TraceHit;
                }
            }
            else
            {
                if (Physics.Raycast(TraceRay, out TraceHit))
                {
                    if (DrawRay)
                    {
                        Debug.DrawLine(TraceRay.origin, TraceHit.point, Color.green, 2);
                    }
                    return TraceHit;
                }
                else
                {
                    if (DrawRay)
                    {
                        Debug.DrawLine(TraceRay.origin, TraceRay.GetPoint(100), Color.green, 2);
                    }
                    return TraceHit;
                }
            }
        }


    }
}